﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Caching;
using mal.balades.Business.DataAccess;
using mal.balades.Business.DataModel;
using mal.balades.Business.Helper;

namespace mal.balades.Business.Manager
{
    public class BaladesManager
    {
        #region Fields
        private BaladesDataContext dataContext;
        private VisitDataAccess visitDataAccess;
        private VisitQualityDataAccess visitQualityDataAccess;
        private FeedDataAccess feedDataAccess;

        private const string GetVisitsForHomePage_KEY = "GetVisitsForHomePage_KEY";
        #endregion

        #region Construction / Destruction
        public BaladesManager()
        {
            this.dataContext = BaladesDataContext.Instance;

            visitDataAccess = new VisitDataAccess(this.dataContext);
        }
        #endregion

        #region enum, struct, class
        private class VisitListOrder
        {
            public VisitList VisitList { get; set; }
            public int Order { get; set; }
        }

        #endregion

        #region Properties
        public FeedDataAccess FeedDataAccess
        {
            get
            {
                if (feedDataAccess == null)
                    feedDataAccess = new FeedDataAccess(dataContext);

                return feedDataAccess;
            }
        }

        public VisitDataAccess VisitDataAccess
        {
            get
            {    
                return visitDataAccess;
            }
        }

        public VisitQualityDataAccess VisitQualityDataAccess
        {
            get
            {
                if (visitQualityDataAccess == null)
                    visitQualityDataAccess = new VisitQualityDataAccess(BaladesDataContext.Instance);

                return visitQualityDataAccess;
            }
        }
        #endregion

        #region Methods
        public IEnumerable<VisitList> GetVisitsForHomePage()
        {

            List<VisitListOrder> visitsToDisplay = HttpContext.Current.Cache[GetVisitsForHomePage_KEY] as List<VisitListOrder>;

            if (visitsToDisplay == null)
            {
                Random rnd = new Random();
                List<VisitList> visits = this.GetAllVisits().ToList();

                visitsToDisplay = new List<VisitListOrder>();

                foreach (VisitList visit in visits)
                {
                    visitsToDisplay.Add(new VisitListOrder() { VisitList = visit, Order = rnd.Next(0, visits.Count) });
                }

                DateTime expirationDate = DateTime.Now.AddDays(1);
                HttpContext.Current.Cache.Insert(GetVisitsForHomePage_KEY, visitsToDisplay, null, expirationDate, Cache.NoSlidingExpiration);
            }

            var query = from v in visitsToDisplay
                        orderby v.Order
                        select v.VisitList;

            return query;
        }

        public IEnumerable<VisitList> GetClosedVisits(int visitId)
        {
            List<VisitList> results = new List<VisitList>();
            List<VisitList> visits = GetAllVisits().ToList();

            VisitList current = visits.FirstOrDefault(v => v.VisitID == visitId);
            if (current != null)
            {
                if (current.Latitude.HasValue && current.Longitude.HasValue)
                {
                    foreach (VisitList visit in visits.ToList())
                    {
                        if (current != visit && visit.Latitude.HasValue && visit.Longitude.HasValue)
                        {
                            double distance = GpsHelper.GetDistance(visit.Latitude.Value, visit.Longitude.Value
                                , current.Latitude.Value, current.Longitude.Value);
                            if (distance < 20)
                            {
                                visit.Distance = distance;
                                results.Add(visit);
                            }
                        }
                    }
                }
            }
            return results;
        }

        public IEnumerable<VisitList> GetAllVisits()
        {
            return VisitDataAccess.GetAllVisits();
        }       

        public List<MapVisitList> GetAllVisitsForMap()
        {
            List<MapVisitList> results = new List<MapVisitList>();

            foreach (VisitList item in GetAllVisits())
            {
                results.Add(new MapVisitList(item));
            }

            return results;
        }

        public MapVisitList GetVisitForMap(string visitUrlName)
        {
            IEnumerable<VisitList> visits = GetAllVisits();
            VisitList visit = visits.FirstOrDefault(v => string.Compare(v.UrlName, visitUrlName, true) == 0);

            if (visit != null)
                return new MapVisitList(visit);
            else
                return new MapVisitList();
        }

        public Visit GetVisit(string visitUrlName)
        {
            return VisitDataAccess.GetVisit(visitUrlName);
        }

        public Visit GetVisit(int visitId)
        {
            return VisitDataAccess.GetVisit(visitId);
        }

        public IEnumerable<Category> GetCateogries()
        {
            return this.dataContext.Categories.OrderBy(c => c.CategoryTypeID);
        }

        public IEnumerable<Information> GetVisitInformations(Visit visit, InformationType.InformationTypeValue type)
        {
            IEnumerable<Information> results = visit.Informations.Where(i => i.InformationTypeID == (int)type).OrderBy(i => i.Rank);
            return results;
        }

        public IEnumerable<Picture> GetVisitPictures(Visit visit, PictureType.PictureTypeValue type)
        {
            IEnumerable<Picture> results = visit.Pictures.Where(p => p.PictureTypeID == (int)type).OrderBy(p => p.Rank);
            return results;
        }
        
        
        #endregion

        #region Events

        #endregion



    }
}
